#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <wait.h>
#include <ctime>
#include <cstring>

void PrintPending()
{
    sigset_t set;
    sigpending(&set);

    for (int i = 31; i >= 1; i--)
    {
        if (sigismember(&set, i))
        {
            std::cout << "1";
        }
        else
            std::cout << "0";
    }
    std::cout << std::endl;
}

// int flag=0;
// volatile可以避免编译器的过度优化，保持内存的可见性
// CPU每次都从内存访问数据 而不是直接从寄存器上读取
volatile int flag = 0;

void handler(int signo)
{
    sleep(5);
    //std::cout << "catch a signo : " << signo << std::endl;

    // while(true)
    // {
    //     PrintPending();
    //     sleep(1);
    // }

    // flag=1;

    // 在捕捉方法里面等待子进程的退出
    // int rid = waitpid(-1, nullptr, 0);
    // std::cout << "wait sucess pid : " << rid << std::endl;
    pid_t rid;
    while ((rid = waitpid(-1, nullptr, WNOHANG)) > 0)
    {
        std::cout << "I am proccess: " << getpid() << " catch a signo: " << signo << "child process quit: " << rid << std::endl;
    }
}

int main()
{

    // signal(17, SIG_IGN); // SIG_DFL -> action -> IGN  忽略系统默认回收退出后的子进程

    srand(time(nullptr));
    signal(17, handler);
    // 如果我们有10个子进程呢？？如果同时退出呢？
    // 如果退出一半呢？
    for (int i = 0; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            while (true)
            {
                std::cout << "I am child process: " << getpid() << ", ppid: " << getppid() << std::endl;
                sleep(5);
                break;
            }
            std::cout << "child quit!!!" << std::endl;
            exit(0);
        }
        sleep(rand()%5+3);
        //sleep(1);
    }
    // father
    while (true)
    {
        std::cout << "I am father process: " << getpid() << std::endl;
        sleep(1);
    }

    return 0;

    // // 子进程退出的时候会给父进程发送SIGCHLD信号
    // signal(17, handler);
    // int n = fork();
    // if (n == 0)
    // {
    //     // child
    //     while (true)
    //     {
    //         std::cout << "I am a child , pid : " << getpid() << " , ppid : " << getppid() << std::endl;
    //         sleep(5);
    //         break;
    //     }
    //     std::cout << "child quit ..." << std::endl;
    //     exit(0);
    // }
    // // parent
    // while (true)
    // {
    //     std::cout << "I am a father , pid : " << getpid() << std::endl;
    //     sleep(1);
    // }

    // return 0;

    // signal(2,handler);
    // //在优化条件下，flag直接被优化到CPU的寄存器上--CPU对flag再次进行检测的时候，直接从寄存器上拿数据
    // //flag也要在内存中开辟空间的

    // while(!flag);
    // std::cout<<"process quit..."<<std::endl;

    // 1.pending图从1->0是在调用信号捕捉方法前就做的
    // 2.信号在被捕捉时 该信号会被放入信号屏蔽字 避免信号捕捉被重复嵌套调用
    //  struct sigaction act,oact;
    //  memset(&act,0,sizeof(act));
    //  memset(&act,0,sizeof(oact));

    // sigemptyset(&act.sa_mask);
    // //添加多个屏蔽信号
    // sigaddset(&act.sa_mask,2);
    // sigaddset(&act.sa_mask,3);
    // sigaddset(&act.sa_mask,4);
    // act.sa_handler = handler;
    // //自定义捕捉方法对所有pending表里存在的信号都有效
    // sigaction(2,&act,&oact);

    // while(true)
    // {
    //     std::cout<<"I m a pricess : "<<getpid()<<std::endl;
    //     sleep(1);
    // }

    return 0;
}